package com.wonderplay.warlord.module.combat;

import java.util.List;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

import com.wonderplay.engine.GameEngine;
import com.wonderplay.engine.LogicEngine;
import com.wonderplay.engine.ModuleChangeNotifier;
import com.wonderplay.engine.ResourceHandler;
import com.wonderplay.warlord.conf.WarLordConf;
import com.wonderplay.warlord.conf.WarLordContants;
import com.wonderplay.warlord.engine.CharacterStatus;
import com.wonderplay.warlord.engine.WarLordResourceHandler;

public class WarLordCombatLogicEngine extends LogicEngine {

	MatrixAdaptor matrixAdaptor;

	public enum LOGIC_STATUS {
		LOGIC_IDLE, LOGIC_SELECT, LOGIC_SWITCH, LOGIC_SWITCH_BACK, LOGIC_ELIMINATE, LOGIC_GENERATE,
		LOGIC_SKILL_RANGE_SELECT, LOGIC_SKILL_EXTRACT
	};

	LOGIC_STATUS status;

	// TODO temp solution
	static final int MOVE_FRAMES = 8;

	Move currentMove = new Move();

	Elimination currentElimination = new Elimination();

	Generation currentGeneration = new Generation();

	Paint paint = new Paint();

	int selectedX, selectedY;

	/***************
	 * 
	 */
	public static int SCREEN_W = 320;
	public static int SCREEN_H = 455;

	final int caseWidth = 40;

//	final int BODY_W = 8;
//	final int BODY_H = 8;

	String test = "";

	int beginDrawX, beginDrawY;

	CharacterCombatStatus selfCombatStatus;
	CharacterCombatStatus opponentCombatStatus;

	boolean playerTurn;

	public WarLordCombatLogicEngine(GameEngine gameEngine, int moduleId) {
		super(gameEngine, moduleId);

		matrixAdaptor = new MatrixAdaptor(WarLordConf.getWidth(), WarLordConf
				.getHeight(), WarLordConf.getEliminateNum(), WarLordConf
				.getTypes());
		matrixAdaptor.generateInitMatrix();

		paint.setColor(Color.GRAY);
		paint.setTextSize(22);

		status = LOGIC_STATUS.LOGIC_IDLE;

		beginDrawX = (SCREEN_W - WarLordConf.getWidth() * caseWidth) >> 1;
		beginDrawY = (SCREEN_H - WarLordConf.getHeight() * caseWidth) >> 1;

		playerTurn = false;
	}

	public void init() {
		matrixAdaptor.generateInitMatrix();
		status = LOGIC_STATUS.LOGIC_IDLE;
	}

	public void startNewCombat(CharacterStatus selfCombatStatus,
			CharacterStatus opponentCombatStatus) {
		this.selfCombatStatus = new CharacterCombatStatus(selfCombatStatus);
		this.opponentCombatStatus = new CharacterCombatStatus(
				opponentCombatStatus);

		playerTurn = true;
	}

	public void updateLogic() {

		switch (status) {
		case LOGIC_IDLE:
			if (playerTurn == false) {
				// choose one move
				List<Suggestion> suggestionList = matrixAdaptor
						.getAllSuggestions();
				if (suggestionList != null && !suggestionList.isEmpty()) {

					Suggestion suggestion = suggestionList.get(0);

					currentMove.setMove(suggestion.x, suggestion.y,
							suggestion.switchType);
					status = LOGIC_STATUS.LOGIC_SWITCH;
				}
			}
			break;
		case LOGIC_SELECT:
			break;
		case LOGIC_SWITCH:
			// currentMove.increaseCurrentMoveFrame();
			// if (currentMove.isMoveFinished()) {

			List<EliminateUnits> unitsList = matrixAdaptor.searchForEliminate(
					currentMove.getX(), currentMove.getY(), currentMove
							.getSwitchType());
			boolean canEliminate = unitsList.size() > 0;

			if (canEliminate) {
				// change matrix
				matrixAdaptor.switchUnit(currentMove.getX(),
						currentMove.getY(), currentMove.getSwitchType());

				List<EliminateCluster> eliminateClusterList = matrixAdaptor
						.destroyEliminable();
				// TODO change status by eliminate clusters

				currentMove.reset();

				status = LOGIC_STATUS.LOGIC_ELIMINATE;
				currentElimination.startEliminate(unitsList);

				for (EliminateUnits units : unitsList) {
					if (playerTurn == true) {
						selfCombatStatus.changeElement(units.unitType,
								units.posList.size());
					} else {
						opponentCombatStatus.changeElement(units.unitType,
								units.posList.size());
					}
				}

			} else {
				status = LOGIC_STATUS.LOGIC_SWITCH_BACK;
				currentMove.switchBack();
			}
			// }
			break;
		case LOGIC_SWITCH_BACK:
			// currentMove.increaseCurrentMoveFrame();
			// if (currentMove.isMoveFinished()) {
			status = LOGIC_STATUS.LOGIC_IDLE;
			currentMove.reset();
			// }
			break;
		case LOGIC_ELIMINATE:
			// destroy units and display

			// currentElimination.increaseCurrentFrame();
			// if (currentElimination.isEliminateFinished()) {

			currentElimination.reset();

			matrixAdaptor.moveUnit();
			matrixAdaptor.fillEmptyUnits();

			currentGeneration.reset();

			status = LOGIC_STATUS.LOGIC_GENERATE;
			// }

			break;
		case LOGIC_GENERATE:
			// generate new units and fall down

			// currentGeneration.increaseCurrentFrame();
			// if (currentGeneration.isGenerateFinished()) {
			List<EliminateUnits> unitsList2 = matrixAdaptor
					.getDestroyableUnitsList();
			boolean canEliminate2 = unitsList2.size() > 0;

			if (canEliminate2) {
				List<EliminateCluster> eliminateClusterList = matrixAdaptor
						.destroyEliminable();
				// TODO change status

				status = LOGIC_STATUS.LOGIC_ELIMINATE;
				currentElimination.startEliminate(unitsList2);
			} else {

				playerTurn = !playerTurn;
				status = LOGIC_STATUS.LOGIC_IDLE;
			}

			List<Suggestion> suggestionList = matrixAdaptor.getAllSuggestions();
			if (suggestionList == null || suggestionList.isEmpty()) {
				moduleChangeNotifier.setMessage(WarLordContants.MODULE_STORY,
						null);
				// sendModuleChangeReq(this.moduleId,
				// WarLordContants.MODULE_STORY, null);
			}

			// }

			break;
		default:
			break;

		}
	}

	@Override
	public void performKeyEvent(KeyEvent keyEvent) {
		// TODO Auto-generated method stub

	}

	@Override
	public void performTouchEvent(MotionEvent touchEvent) {

		switch (touchEvent.getAction()) {
		case MotionEvent.ACTION_DOWN:
			if (playerTurn == false || status == LOGIC_STATUS.LOGIC_SWITCH
					|| status == LOGIC_STATUS.LOGIC_SWITCH_BACK
					|| status == LOGIC_STATUS.LOGIC_ELIMINATE
					|| status == LOGIC_STATUS.LOGIC_GENERATE) {
				return;
			}

			float x = touchEvent.getX();
			float y = touchEvent.getY();

			if (x > beginDrawX && x < beginDrawX + caseWidth * WarLordConf.getWidth()
					&& y > beginDrawY && y < beginDrawY + caseWidth * WarLordConf.getHeight()) {
				if (status == LOGIC_STATUS.LOGIC_SELECT) {
					int tempX = (int) ((x - beginDrawX) / caseWidth);
					int tempY = (int) ((y - beginDrawY) / caseWidth);

					if (tempX > selectedX) {
						if (tempY > selectedY) {
							// do nothing
						} else if (tempY == selectedY) {
							move(selectedX, selectedY, MainMatrix.SWITCH_RIGHT);
						} else if (tempY < selectedY) {
							// do nothing
						}
					} else if (tempX == selectedX) {
						if (tempY > selectedY) {
							move(selectedX, selectedY, MainMatrix.SWITCH_DOWN);
						} else if (tempY == selectedY) {
							status = LOGIC_STATUS.LOGIC_IDLE;
						} else if (tempY < selectedY) {
							move(selectedX, selectedY, MainMatrix.SWITCH_UP);
						}
					} else if (tempX < selectedX) {
						if (tempY > selectedY) {
							// do nothing
						} else if (tempY == selectedY) {
							move(selectedX, selectedY, MainMatrix.SWITCH_LEFT);
						} else if (tempY < selectedY) {
							// do nothing
						}
					}
				} else {
					status = LOGIC_STATUS.LOGIC_SELECT;

					selectedX = (int) ((x - beginDrawX) / caseWidth);
					selectedY = (int) ((y - beginDrawY) / caseWidth);
				}
			}else{
				//extract sill
				if (playerTurn == true){
					if (status == LOGIC_STATUS.LOGIC_IDLE){
						
					}
				}
				
			}
		}

		// this will cause ConcurrentModificationException
		// for (MotionEvent e:touchEvent){
		// test += e.getX() + ", " + e.getY() + ";";
		// }

	}

	private void move(int x, int y, int switchType) {

		status = LOGIC_STATUS.LOGIC_SWITCH;
		currentMove.setMove(x, y, switchType);

	}

	@Override
	// this function runs on main thread
	public void drawCanvas(Canvas canvas) {

		ResourceHandler rawHandler = gameEngine.getResourceHandler();
		WarLordResourceHandler handler = null;
		if (rawHandler instanceof WarLordResourceHandler) {
			handler = (WarLordResourceHandler) rawHandler;
		}

		canvas.drawColor(Color.WHITE);
		canvas.clipRect(0, 0, SCREEN_W, SCREEN_H);
		canvas.drawBitmap(handler.bmTop, 0, 0, paint);
		canvas.drawBitmap(handler.bmTop, 0, SCREEN_H
				- handler.bmTop.getHeight(), paint);

		int[][] matrix = matrixAdaptor.getMatrix();

		ResourceHandler resourceHandlerTemp = gameEngine.getResourceHandler();

		WarLordResourceHandler resourceHandler = (WarLordResourceHandler) resourceHandlerTemp;

		for (int i = 0; i < WarLordConf.getWidth(); i++) {
			for (int j = 0; j < WarLordConf.getHeight(); j++) {
				if (matrix[i][j] >= 0) {
					canvas.save();
					canvas.clipRect(beginDrawX, beginDrawY, beginDrawX
							+ caseWidth * WarLordConf.getWidth(), beginDrawY + caseWidth
							* WarLordConf.getHeight());
					canvas.drawBitmap(resourceHandler.block[matrix[i][j]],
							beginDrawX + i * caseWidth, beginDrawY + j
									* caseWidth, paint);
					canvas.restore();
				}
			}
		}

		if (status == LOGIC_STATUS.LOGIC_SELECT) {
			canvas.save();
			canvas.clipRect(beginDrawX, beginDrawY, beginDrawX + caseWidth
					* WarLordConf.getWidth(), beginDrawY + caseWidth * WarLordConf.getHeight());
			canvas.drawBitmap(resourceHandler.cursor1, beginDrawX + selectedX
					* caseWidth, beginDrawY + selectedY * caseWidth, paint);
			canvas.restore();
		}

		canvas.drawText(selfCombatStatus.toString(), 0, 20, paint);

		canvas.drawText(opponentCombatStatus.toString(), 0, SCREEN_H
				- handler.bmTop.getHeight(), paint);
	}

	@Override
	public void reset() {
		status = LOGIC_STATUS.LOGIC_IDLE;
		playerTurn = false;
		this.selfCombatStatus = null;
		this.opponentCombatStatus = null;
	}
}

class Move {
	int x;
	int y;
	int switchType;

	int currentMoveFrame;

	public Move() {
		x = 0;
		y = 0;
		switchType = MainMatrix.SWITCH_INVALID;
		currentMoveFrame = 0;
	}

	public Move(int x, int y, int switchType) {
		this.x = x;
		this.y = y;
		this.switchType = switchType;
		currentMoveFrame = 0;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public int getSwitchType() {
		return switchType;
	}

	public void setSwitchType(int switchType) {
		this.switchType = switchType;
	}

	public void reset() {
		x = 0;
		y = 0;
		switchType = MainMatrix.SWITCH_INVALID;
	}

	public void setMove(int x, int y, int switchType) {
		this.x = x;
		this.y = y;
		this.switchType = switchType;

		currentMoveFrame = 0;
	}

	public int getCurrentMoveFrame() {
		return currentMoveFrame;
	}

	public void increaseCurrentMoveFrame() {
		currentMoveFrame++;
	}

	public boolean isMoveFinished() {
		return currentMoveFrame >= 8;
	}

	public void switchBack() {
		currentMoveFrame = 0;
	}
}

class Elimination {
	List<EliminateUnits> unitsList;

	int currentFrame;

	public void startEliminate(List<EliminateUnits> unitsList) {
		this.unitsList = unitsList;
		currentFrame = 0;
	}

	public void increaseCurrentFrame() {
		currentFrame++;
	}

	public boolean isEliminateFinished() {
		return currentFrame >= 8;
	}

	public void reset() {
		unitsList = null;
		currentFrame = 0;
	}
}

class Generation {
	int currentFrame = 0;

	public void increaseCurrentFrame() {
		currentFrame++;
	}

	public boolean isGenerateFinished() {
		return currentFrame >= 8;
	}

	public void reset() {
		currentFrame = 0;
	}
}

